/**
 *  Serponix is an arcade game in focus to multiplayer based on the classic game Snake.
 *  Copyright (C) 2010 - 2011  Daniel Vala
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License,
 *  or  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.

 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *  If you have any question do not hesitate to contact author
 *  on e-mail address: danielvala42@gmail.com
 */
package com.serponix.game;

import com.serponix.gui.WindowInterface;
import com.serponix.game.score.Score;
import com.serponix.game.projectiles.Laser;
import com.serponix.game.projectiles.Rocket;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.swing.JLabel;
import com.serponix.game.food.Cherry;
import com.serponix.game.food.Cake;
import com.serponix.game.objektyNaPlose.Clanek;
import java.awt.AlphaComposite;
import com.serponix.net.Informace;

/**
 * Model pro hru klient obsahuje políčka, které každý krok vykresluje.
 * @author Daniel Vala
 */
public class ModelClient extends GameModel {

    private List<Policko> policka;
    private ReentrantReadWriteLock zamek;

    public ModelClient(WindowInterface okno, GameParameters parametryHry, GamingArea herniPanel, JLabel[] skoreStitky, MessagePanel panelZprav) {
        super(okno, parametryHry, herniPanel, skoreStitky, panelZprav, parametryHry.getSizeOfGamingArea());
        parametryHry.getClient().setModel(this);
        net = parametryHry.getClient();
        policka = new ArrayList<Policko>();
        zamek = new ReentrantReadWriteLock();
    }

    /**
     * Přidá do pole políčko, které klient v příštím kroku hry vykreslí.
     * @param policko Políčko k vykreslení.
     */
    public void pridejPolicko(Policko policko) {
        zamek.writeLock().lock();
        try {
            policka.add(policko);
        } finally {
            zamek.writeLock().unlock();
        }
    }

    public void smazVsechnyPolicka() {
        zamek.writeLock().lock();
        try {
            policka.clear();
        } finally {
            zamek.writeLock().unlock();
        }
    }

    public void posliPrikazServeru(String prikaz) {
        net.poslatData(prikaz);
    }

    public void posliPrikazServeru(int prikaz) {
        net.poslatData(prikaz + "");
    }

    public void posliNastaveniHry() {
    }

    public void posliStav() {
    }

    @Override
    public void resetHada(Snake had) {
    }

    @Override
    public void newRound() {
    }

    @Override
    public void jidloSezrano(Snake had) {
    }

    @Override
    public void bonusSezran(Snake had) {
    }

    @Override
    public void addScore(Score skore, int body) {
    }

    @Override
    public void krok() {
        setChanged();
        notifyObservers();
    }

    @Override
    public void paint(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        zamek.readLock().lock();
        try {
            for (Policko policko : policka) {

                // pokud políčko obsahuje barvu
                if (policko.getBarva() != null) {
                    g2d.setPaint(policko.getBarva());
                }
                if (policko.getTyp() == Informace.HAD) {
                    int informace = policko.getInformace();
                    if (policko.getNeviditelnost()) {
                        Clanek.NastavNeviditelneKresleni(g2d);
                    }
                    switch (informace) {
                        case Informace.CLANEK:
                            Clanek.paint(g2d, policko.getX(), policko.getY(), getVelikostPolicka());
                            break;
                        case Informace.ODOLNOST:
                            Clanek.paintOdolny(g2d, policko.getX(), policko.getY(), getVelikostPolicka());
                            break;
                        case Informace.DUCH:
                            Clanek.paintDuch(g2d, policko.getX(), policko.getY(), getVelikostPolicka());
                            break;
                        case Informace.HLAVA:
                            Clanek.paintHlava(g2d, policko.getX(), policko.getY(), getVelikostPolicka(), policko.getSmer());
                            break;
                        case Informace.HLAVA_TANKU:
                            Clanek.paintHlavaTank(g2d, policko.getX(), policko.getY(), getVelikostPolicka(), policko.getSmer());
                            break;
                    }
                    // nastavení průhlednosti zpět na normální hodnotu
                    g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1));
                } else if (policko.getTyp() == Informace.LASER) {
                    Laser.paint(g2d, policko.getX(), policko.getY(), policko.getSmer());
                } else if (policko.getTyp() == Informace.RAKETA) {
                    Rocket.paint(g2d, policko.getX(), policko.getY(), policko.getSmer());
                } else if (policko.getTyp() == Informace.JIDLO) {
                    Cake.paint((Graphics2D) g, policko.getX(), policko.getY());
                } else if (policko.getTyp() == Informace.BONUS) {
                    Cherry.paint((Graphics2D) g, policko.getX(), policko.getY());
                } else if (policko.getTyp() == Informace.SMAZ_ZED) {
                    getMapa().smazZed(policko.getX(), policko.getY());
                }
            }
        } finally {
            zamek.readLock().unlock();
        }
        smazVsechnyPolicka();
    }

    @Override
    void paintZdi(Graphics g) {
        getMapa().kresliMapu(g);
    }
}
